﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;

namespace Asteroids.Game
{
    public class Player : IUpdate, ICollide
    {
        public Ship CurrentShip { get; set; }
        public int Ticks { get; set; }
        private bool[] KeysPressed;

        private const int UpdateTicksImmortalAfterHit = 40;
        private int _currentTicks;

        private int _numShips;
        public int NumShips
        {
            get { return _numShips; }
            set
            {
                _numShips = value;
                if (PlayerShipCountChanged != null)
                    PlayerShipCountChanged(this, EventArgs.Empty);
            }
        }

        private int _score;
        public int Score
        {
            get { return _score; }
            set
            {
                _score = value;
                if (OnPlayerScoreChanged != null)
                    OnPlayerScoreChanged(this, EventArgs.Empty);
            }
        }

        public Player()
        {
            NumShips = 3;
            CurrentShip = new Ship(new Coordinate(100, 100));
            CurrentShip.Shield = 1;
            CurrentShip.OnDeath += OnShipDeath;

            KeysPressed = new bool[5];

            MainWindow.KeyDownEvent += KeyDown;
            MainWindow.KeyUpEvent += KeyUp;

            _currentTicks = 0;
        }

        public void OnShipDeath(object s, EventArgs e)
        {
            CurrentShip.OnDeath -= OnShipDeath;

            //MainWindow.Timer.Stop();
            Game.Instance.IsPaused = true;

            if (NumShips - 1 < 0)
            {
                if (OnPlayerDeath != null)
                    OnPlayerDeath(this, EventArgs.Empty);
            } else
                NumShips -= 1;

            SetUpAnimation();
        }

        public void SetUpAnimation()
        {

            Ticks = 20;

            MainWindow.Timer.Tick += DeathAnimation;
        }

        public void DeathAnimation(object s, EventArgs e)
        {
            Ticks--;
            if (Ticks > 0)
            {
                foreach (var polarCoordinate in CurrentShip.VertexData)
                {
                    polarCoordinate.Angle += Game.Random.NextDouble();
                    polarCoordinate.Magnitude += Game.Random.NextDouble();
                }

                MainWindow.Instance.GameScreenUC.Render(this, EventArgs.Empty);
            } 
            else
            {
                ResetVertexData();
                MainWindow.Timer.Tick -= DeathAnimation;
                Game.Instance.IsPaused = false;
            }
        }

        public void ResetVertexData()
        {
            var tcoord = CurrentShip.Location;
            var tdir = CurrentShip.FaceDirection;
            CurrentShip = new Ship(tcoord) { FaceDirection = tdir };
            CurrentShip.OnDeath += OnShipDeath;
        }

        public void Update(UpdateEventArgs e)
        {
            _currentTicks++;
            CurrentShip.UpdateInput(KeysPressed);
            CurrentShip.Brush = !IsVulnerable() ? Brushes.LimeGreen : Brushes.LightSteelBlue;
            CurrentShip.Update(e);
        }

        public bool IsWithinOf(double range, ICollide collidable)
        {
            return CurrentShip.IsWithinOf(range, collidable);
        }

        public bool TestCollideWith(ICollide collidable)
        {
            return CurrentShip.TestCollideWith(collidable);
        }

        public void Collide(CollideEventArgs e)
        {
            if (IsVulnerable())
            {
                CurrentShip.Collide(e);
                _currentTicks = 0;
            }
        }

        public bool IsVulnerable()
        {
            return _currentTicks > UpdateTicksImmortalAfterHit;
        }

        public Coordinate Location
        {
            get { return CurrentShip.Location; }
            set { CurrentShip.Location = value; }
        }

        public double Radius
        {
            get { return CurrentShip.Radius; }
            set { CurrentShip.Radius = value; }
        }

        #region KeyInput
        public void KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.Up:
                    KeysPressed[0] = true;
                    break;
                case Key.Down:
                    KeysPressed[1] = true;
                    break;
                case Key.Right:
                    KeysPressed[2] = true;
                    break;
                case Key.Left:
                    KeysPressed[3] = true;
                    break;
                case Key.Space:
                    KeysPressed[4] = true;
                    break;
            }
        }

        public void KeyUp(object sender, KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.Up:
                    KeysPressed[0] = false;
                    break;
                case Key.Down:
                    KeysPressed[1] = false;
                    break;
                case Key.Right:
                    KeysPressed[2] = false;
                    break;
                case Key.Left:
                    KeysPressed[3] = false;
                    break;
                case Key.Space:
                    KeysPressed[4] = false;
                    break;
            }
        }
        #endregion

        public EventHandler OnPlayerScoreChanged;
        public EventHandler PlayerShipCountChanged;
        public EventHandler OnPlayerDeath;
    }
}
